package cn.fzkj.gulimall.auth.controller;

import cn.fzkj.common.constant.AuthConstant;
import cn.fzkj.common.exception.ErrorsEnum;
import cn.fzkj.common.utils.R;
import cn.fzkj.gulimall.auth.entity.LoginEntity;
import cn.fzkj.gulimall.auth.entity.RegisterEntity;
import cn.fzkj.gulimall.auth.feign.MemberFeignService;
import cn.fzkj.gulimall.auth.feign.SmsFeignService;
import cn.fzkj.gulimall.auth.redis.RedisCache;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @DESCRIPTION 登陆、注册接口
 * @Author yaya
 * @DATE 2022/8/20
 */
@Slf4j
@RestController
@RequestMapping("/auth")
public class AuthController {

    @Autowired
    private SmsFeignService smsFeignService;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private MemberFeignService memberFeignService;

    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public R login(@RequestBody LoginEntity entity){
        return memberFeignService.login(entity);
    }

    @RequestMapping(value = "/register", method = RequestMethod.POST)
    public R register(@Valid @RequestBody RegisterEntity entity, BindingResult result){

        if (result.hasErrors()){
            Map<String, String> errors = result.getFieldErrors().stream().collect(Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage));
            return R.error(ErrorsEnum.REGISTER_FAIL).data(errors);
        }

        // 验证验证码
        String codeStr = redisCache.get(AuthConstant.SMS_CACHE_PREFIX + entity.getPhoneNum());
        try {
            String code = codeStr.split("_")[0];
            if (!entity.getCode().equalsIgnoreCase(code)){
                return R.error(ErrorsEnum.SMS_NOT_CURRENT);
            }
            // 删除验证码；类似令牌机制
            redisCache.del(AuthConstant.SMS_CACHE_PREFIX + entity.getPhoneNum());

            // 调用远程服务注册
            return memberFeignService.register(entity);
        } catch (Exception e) {
            log.warn("code validate fail. {}", e.getMessage());
            return R.error(ErrorsEnum.SMS_NOT_CURRENT);
        }
    }

    /**
     * 发送短信验证码
     * @param phone
     * @return
     */
    @RequestMapping(value = "/sendCode", method = RequestMethod.GET)
    public R sendCode(@RequestParam("phone") String phone){

        // TODO 接口防刷
        String cacheCode = redisCache.get(AuthConstant.SMS_CACHE_PREFIX + phone);
        boolean toManyRequest;
        try {
            toManyRequest = StringUtils.isNotEmpty(cacheCode) && System.currentTimeMillis() - Long.parseLong(cacheCode.split("_")[1]) < 60000;
        } catch (NumberFormatException e) {
            log.warn("parse phone code fail, the exception message is {}", e.getMessage());
            toManyRequest = true;
        }
        if (toManyRequest){
            return R.error(ErrorsEnum.SMS_REQUEST_REFUSE);
        }

        String code = UUID.randomUUID().toString().substring(0, 5);

        // key -> sms:code:phone; value -> code
        redisCache.set(AuthConstant.SMS_CACHE_PREFIX + phone, code + "_" + System.currentTimeMillis(), 600, TimeUnit.SECONDS);

        smsFeignService.sendSms(phone, code);
        return R.ok();
    }

}
